package org.simplesocket.simplenettycore.handlers;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;
import org.simplesocket.simplenettycore.protocol.Request;
import org.simplesocket.simplenettycore.protocol.SimpleProtocol;
import org.simplesocket.simplenettycore.session.ChannelAttr;
import org.simplesocket.simplenettycore.session.ClientSessionContext;
import org.simplesocket.simplenettycore.utils.CommonUtils;
import org.simplesocket.simplenettycore.utils.SimpleNettyUtils;

import java.util.Map;

@Slf4j
@ChannelHandler.Sharable
public class DecryptHandler extends SimpleChannelInboundHandler<SimpleProtocol> {
    
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, SimpleProtocol sp) {
        ClientSessionContext csc = ctx.channel().attr(ChannelAttr.CLIENT_SESSION_CONTEXT).get();
        String aes = csc.getBothAes();
        String decrypted = null;
        try {
            String dataStr = sp.getData();
            if (!StrUtil.isBlank(dataStr)){
                decrypted = SimpleNettyUtils.AESUtil.decrypt(dataStr, aes);
            }
        }catch (Exception e){
            // 解密失败
            log.error("Decrypt client '{}' data error,sessionID is '{}':\n",
                    ctx.channel().remoteAddress(),sp.getSessionID());
            CommonUtils.printException(e);
            
            ctx.writeAndFlush(SimpleProtocol.builder()
                            .type(sp.getType())
                            .status(SimpleProtocol.Status.ERROR)
                            .sessionID(sp.getSessionID())
                            .data(JSON.toJSONString(Map.of("sessionID","Protocol transform error")))
                    .build());// 给客户端返回错误
            sp.recycle();
            return;
        }
        
        try {
            Map<String,?> params = null;
            if (!StrUtil.isBlank(decrypted)){
                params = JSON.parseObject(decrypted, new TypeReference<>(){});
            }
            ctx.fireChannelRead(new Request.Builder()
                            .uri(sp.getUri())
                            .csc(ctx.channel().attr(ChannelAttr.CLIENT_SESSION_CONTEXT).get())
                            .params(params)
                            .sessionID(sp.getSessionID())
                    .build());
        }catch (Exception e){
            // JSON转换失败，一般是格式不符合要求
            log.error("Parse client '{}' data error,sessionID is '{}',\n",
                    ctx.channel().remoteAddress(),sp.getSessionID());
            CommonUtils.printException(e);
            
            ctx.writeAndFlush(SimpleProtocol.builder()
                            .type(sp.getType())
                            .status(SimpleProtocol.Status.ERROR)
                            .sessionID(sp.getSessionID())
                            .data(JSON.toJSONString(Map.of("sessionID","Protocol translate error")))
                    .build());
        }finally {
            sp.recycle();
        }
    }
    
}
